#pragma once
#ifdef LIT_OGRE_SUPPORT

#ifndef __LIT__SCENE__FILE__HH__
#define __LIT__SCENE__FILE__HH__

#include "LitSceneLoader.h"
#include "LitEntity.h"

#include <OgreResourceManager.h>

namespace Lit
{
	class XmlScene : public Ogre::Resource
	{
	protected:
 
		// must implement these from the Ogre::Resource interface
		void loadImpl();
		void unloadImpl();
		size_t calculateSize() const;
	public:
		typedef std::map<String,EntityPtr> EntityMap;
		
	protected:
		OgreSceneManagerPtr		mSceneMgr;
		OgreSceneNodePtr		mNode;
		EntityMap				mMap;
		Ogre::DotSceneLoader	mLoader;

	public:

		XmlScene(Ogre::ResourceManager *creator, const Ogre::String &name, 
			Ogre::ResourceHandle handle, const Ogre::String &group, bool isManual = false, 
			Ogre::ManualResourceLoader *loader = 0);
		XmlScene( const XmlScene &rk );
		virtual ~XmlScene( );

		void setSceneManager( OgreSceneManagerPtr mgr );
		OgreSceneManagerPtr sceneManager() const;

		void clear();
		void createScene( const String &filename, Ogre::SceneManager *mgr, const String& resource_group = Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME );
		void createScene( Ogre::DataStreamPtr &strm, Ogre::SceneManager *mgr, const String& resource_group = Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME );
		void _destroyChildNodes( Ogre::SceneNode* n );
		void destroyScene( );
	public:
 
		void loadFromStream( Ogre::DataStreamPtr& pStream );
		void loadFromFile( const String &fname );
	};
 
	class XmlScenePtr : public Ogre::SharedPtr<XmlScene> 
	{
	public:
		XmlScenePtr() : Ogre::SharedPtr<XmlScene>() {}
		explicit XmlScenePtr(XmlScene *rep) : Ogre::SharedPtr<XmlScene>(rep) {}
		XmlScenePtr(const XmlScenePtr &r) : Ogre::SharedPtr<XmlScene>(r) {} 
		XmlScenePtr(const Ogre::ResourcePtr &r) : Ogre::SharedPtr<XmlScene>()
		{
			if( r.isNull() )
				return;
			// lock & copy other mutex pointer
			OGRE_LOCK_MUTEX(*r.OGRE_AUTO_MUTEX_NAME)
			OGRE_COPY_AUTO_SHARED_MUTEX(r.OGRE_AUTO_MUTEX_NAME)
			pRep = static_cast<XmlScene*>(r.getPointer());
			pUseCount = r.useCountPointer();
			useFreeMethod = r.freeMethod();
			if (pUseCount)
			{
				++(*pUseCount);
			}
		}
 
		/// Operator used to convert a ResourcePtr to a ScenePtr
		XmlScenePtr& operator=(const Ogre::ResourcePtr& r)
		{
			if(pRep == static_cast<XmlScene*>(r.getPointer()))
				return *this;
			release();
			if( r.isNull() )
				return *this; // resource ptr is null, so the call to release above has done all we need to do.
			// lock & copy other mutex pointer
			OGRE_LOCK_MUTEX(*r.OGRE_AUTO_MUTEX_NAME)
			OGRE_COPY_AUTO_SHARED_MUTEX(r.OGRE_AUTO_MUTEX_NAME)
			pRep = static_cast<XmlScene*>(r.getPointer());
			pUseCount = r.useCountPointer();
			useFreeMethod = r.freeMethod();
			if (pUseCount)
			{
				++(*pUseCount);
			}
			return *this;
		}
	};
	class XmlSceneSerializer : public Ogre::Serializer
	{
	public:
		XmlSceneSerializer();
		virtual ~XmlSceneSerializer();
 
		void exportScene(const XmlScene *pText, const Ogre::String &fileName);
		void importScene(Ogre::DataStreamPtr &stream, XmlScene *pDest);
	}; 
	class XmlSceneManager : public Ogre::ResourceManager, public Ogre::Singleton<XmlSceneManager>
	{
	protected:
 
		// must implement this from ResourceManager's interface
		Ogre::Resource *createImpl(const Ogre::String &name, Ogre::ResourceHandle handle, 
			const Ogre::String &group, bool isManual, Ogre::ManualResourceLoader *loader, 
			const Ogre::NameValuePairList *createParams);
 
		OgreSceneManagerPtr mSceneMgr;
	public:
		XmlSceneManager();
		virtual ~XmlSceneManager();
 
		void initialise(OgreRenderWindowPtr win, OgreCameraPtr cam, OgreSceneManagerPtr mgr );
		void shutdown();

		virtual XmlScenePtr load(const Ogre::String &name, const Ogre::String &group = Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME);
		static XmlSceneManager &getSingleton();
		static XmlSceneManager *getSingletonPtr();

		const Ogre::StringVector& getScriptPatterns(void);
		void parseScript(Ogre::DataStreamPtr& stream, const Ogre::String& groupName);
		Ogre::Real getLoadingOrder(void) const;

		static String RESOURCE_TYPE;
	};

	typedef RefPtr<XmlSceneManager> XmlSceneManagerPtr;
};
#endif

#endif // IF DEFINED LIT_OGRE_SUPPORT